/* tcpaudioserver.cpp
 * Program to setup socket for audio communication with iPhone app.
 * Listens for connections on TCP port specified by PORT, writes audio
 * file data and plays the audio files by spawning an mplayer process. */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <strings.h>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#define PORT 6000
#define BUFFER_SIZE 4
#define NUM_OUTFILES 5
using namespace std;


int main()
{
    int sock, connected, bytes_recieved , true_var = 1;  
    char recv_data;       
    struct sockaddr_in server_addr,client_addr;    
    socklen_t sin_size;
    char poundBuffer[BUFFER_SIZE];
    char qBuffer[BUFFER_SIZE];
    int poundCount = 0;
    int qCount = 0;
    ofstream outStream; // Stream to write to audio file
    pid_t pID; // Track PID for mplayer process.
    int intOutfileCount = 1;
    string strOutfileCount;
    stringstream out;
    string outfileName = "";
    char currDir[1024];
    string strCurrDir;
    string blackhole;

    // Get current working directory
    getcwd(currDir, sizeof(currDir));
    //cout << "Current directory is: " << currDir << endl;
    strCurrDir = currDir;

    // Get outfileName
    out << intOutfileCount;
    strOutfileCount = out.str();
    outfileName = strCurrDir + "/outfile" + strOutfileCount + ".aac";

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("Socket");
        exit(1);
    }

    if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true_var,sizeof(int)) == -1)
    {
        perror("Setsockopt");
        exit(1);
    }
    
    server_addr.sin_family = AF_INET;         
    server_addr.sin_port = htons(PORT);     
    server_addr.sin_addr.s_addr = INADDR_ANY; 
    bzero(&(server_addr.sin_zero),8); 

    if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
    {
        perror("Unable to bind");
        exit(1);
    }

    if (listen(sock, 5) == -1)
    {
        perror("Listen");
        exit(1);
    }
		
	printf("TCPServer Waiting for client on port %d\n", PORT);
    fflush(stdout);

    while(1)
    {  
        sin_size = sizeof(struct sockaddr_in);
        connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size);
        printf("I got a connection from (%s , %d)\n",
                inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
        outStream.open(outfileName.c_str(), ios_base::binary);
        poundCount = 0;
        while (1)
        {
            bytes_recieved = recv(connected,&recv_data,1,0);
            fflush(stdout);

            if (recv_data == '#')
            {
                poundBuffer[poundCount] = recv_data;
                poundCount++;
                //cout << "Received a '#'. poundCount = " << poundCount << endl;
                recv_data = '\0';
                if (poundCount == BUFFER_SIZE)
                {
                    //cout << "File finished writing. Sleeping...\n";
                    outStream.close();
                    //play aac file with mplayer
                    pID = fork();
                    if (pID == 0)
                    {
                        execl("/usr/bin/mplayer", "/usr/bin/mplayer", outfileName.c_str(), NULL);
                    }
                    //cout << "Reopening outfile.aac\n";
                    intOutfileCount++;
                    if (intOutfileCount > NUM_OUTFILES)
                    {
                        intOutfileCount = 1;
                    }
                    out.str(""); 
                    out << intOutfileCount;

                    strOutfileCount = out.str();
                    outfileName = strCurrDir + "/outfile" + strOutfileCount + ".aac";
                    outStream.open(outfileName.c_str(), ios_base::binary);
                    poundCount = 0;
                }
            }
            else if ((recv_data == 'q') || (recv_data == 'Q'))
            {
                qBuffer[qCount] = recv_data;
                qCount++;
                //cout << "Received a 'q'. qCount = " << qCount << endl;
                recv_data = '\0';
                if (qCount == 4)
                {
                    printf("Closing server\n");
                    fflush(stdout);
                    close(connected);
                    recv_data = '\0';
                    qCount = 0;
                    outStream.close();
                    break;
                }
            }
            else
            {
                if (poundCount > 0)
                {
                    for (int i=0; i < poundCount; i++)
                    {
                        outStream << poundBuffer[i];
                        poundBuffer[i] = '0';
                    }
                }
                if (qCount > 0)
                {
                    for (int i=0; i < qCount; i++)
                    {
                        outStream << qBuffer[i];
                        qBuffer[i] = '0';
                    }
                }
                outStream << recv_data;
                poundCount = 0;
                qCount = 0;
            }
        }
    } 
    close(sock);
    return 0;
} 
